const { createApp, ref, reactive, onMounted, watch, computed } = Vue;

function fetchJson(url) {
    return fetch(url, { headers: { 'x-request-id': crypto.randomUUID?.() || Date.now().toString() } })
        .then((res) => {
            if (!res.ok) throw new Error('HTTP ' + res.status);
            return res.json();
        });
}

createApp({
    setup() {
        const loading = ref(false);
        const downloads = ref([]);
        const logs = ref([]);
        const currentJob = ref('');

        const page = reactive({ limit: 20, offset: 0 });
        const logsPage = reactive({ limit: 200, offset: 0 });

        const query = reactive({ jobId: '', status: '' });
        const autoRefresh = reactive({ enabled: true, intervalMs: 2000, timer: null });

        const pageNumber = computed(() => Math.floor(page.offset / page.limit) + 1);
        const logsPageNumber = computed(() => Math.floor(logsPage.offset / logsPage.limit) + 1);

        function formatPercent(val) {
            if (val == null) return '-';
            return `${Math.round(Number(val))}%`;
        }
        function formatSpeed(bps) {
            if (!bps) return '-';
            const kb = bps / 1024;
            if (kb < 1024) return `${kb.toFixed(1)} KB/s`;
            const mb = kb / 1024;
            return `${mb.toFixed(2)} MB/s`;
        }

        async function loadDownloads() {
            loading.value = true;
            try {
                const params = new URLSearchParams();
                params.set('limit', String(page.limit));
                params.set('offset', String(page.offset));
                if (query.status) params.set('status', query.status);
                const data = await fetchJson(`/api/downloads?${params.toString()}`);
                let items = Array.isArray(data.items) ? data.items : [];
                if (query.jobId) {
                    items = items.filter((d) => String(d.id).includes(query.jobId));
                }
                downloads.value = items;
            } finally {
                loading.value = false;
            }
        }

        async function loadLogs() {
            if (!currentJob.value) {
                logs.value = [];
                return;
            }
            const params = new URLSearchParams();
            params.set('limit', String(logsPage.limit));
            params.set('offset', String(logsPage.offset));
            const data = await fetchJson(`/api/downloads/${encodeURIComponent(currentJob.value)}/logs?${params.toString()}`);
            logs.value = Array.isArray(data.items) ? data.items : [];
        }

        function pageUp() {
            page.offset += page.limit;
            loadDownloads();
        }
        function pageDown() {
            page.offset = Math.max(0, page.offset - page.limit);
            loadDownloads();
        }

        function logsPageUp() {
            logsPage.offset += logsPage.limit;
            loadLogs();
        }
        function logsPageDown() {
            logsPage.offset = Math.max(0, logsPage.offset - logsPage.limit);
            loadLogs();
        }

        function selectJob(id) {
            currentJob.value = id;
            logsPage.offset = 0;
            loadLogs();
        }

        function refreshAll() {
            loadDownloads();
            loadLogs();
        }

        onMounted(() => {
            loadDownloads();
            autoRefresh.timer = setInterval(() => {
                if (autoRefresh.enabled) {
                    refreshAll();
                }
            }, autoRefresh.intervalMs);
        });

        watch(() => autoRefresh.intervalMs, (val) => {
            if (autoRefresh.timer) clearInterval(autoRefresh.timer);
            autoRefresh.timer = setInterval(() => {
                if (autoRefresh.enabled) {
                    refreshAll();
                }
            }, val);
        });

        return {
            loading,
            downloads,
            logs,
            currentJob,
            query,
            autoRefresh,
            page,
            logsPage,
            pageNumber,
            logsPageNumber,
            formatPercent,
            formatSpeed,
            pageUp,
            pageDown,
            logsPageUp,
            logsPageDown,
            selectJob,
            refreshAll,
        };
    },
}).mount('#app');

